/***************************************************
* @版权：哈尔滨工业大学自动化测试与控制研究所
* @文件名：HITATCI_PCM.c
* @作者：Liu Yanku
* @版本：V1.0
* @时间：2023-4-13
* @功能描述：接收产品PCM码流数据
* @修改日志：
***************************************************/

//本库使用的头文件
#include <windows.h>
#include "lib_hitmc_pxie_opt.h"
#include "libStandard_pxie.h" 

/* 
 * @函数名：	HITATCI_PXIe_init
 * @描述：		初始化PXIe模块，获取仪器句柄
 * @输入参数1：	ResourceName		-	仪器的逻辑地址
 * @输入参数2：	IdQuery  	 		-	TRUE：进行仪器识别
										FALSE：不进行仪器识别
 * @输入参数3：	Reset 				-	TRUE：复位仪器
										FALSE：不复位仪器
 * @输出参数1：	viPCM				-	仪器句柄
 * @返回值：	函数执行正确，返回值大于等于0；执行时产生错误，返回值小于0
*/
ViStatus _VI_FUNC HITATCI_PXIe_init (ViRsrc ResourceName, ViBoolean IdQuery, ViBoolean Reset, ViSession *viPCM)
{
    ViStatus ret = 0;
	ViUInt16 vendor_id_data = 0;
	ViUInt16 device_id_data = 0;
	ViUInt16 pci_slot_id = 0;
	ViUInt16 pci_bus_id = 0;

   	//打开设备
    ret = PXIe_viOpen (0, ResourceName, 0, 0, viPCM);

	// 获取设备ID
	PXIe_viDevmsg(*viPCM, &vendor_id_data, &device_id_data, &pci_slot_id, &pci_bus_id);

	// 返回函数操作结果
	return ret;
}

/*
 * @函数名：	HITATCI_PXIe_Close
 * @描述：		关闭PXIe模块，释放仪器句柄
 * @输入参数1：	vi			-	仪器句柄
 * @返回值：	函数执行正确，返回值大于等于0；执行时产生错误，返回值小于0
*/
ViStatus _VI_FUNC HITATCI_PXIe_Close (ViSession vi)
{
	ViStatus ret = 0;

	// 关闭设备
    ret = PXIe_viClose(vi);

	// 返回关闭函数结果
	return ret;
}

/*
 * @函数名：	HITATCI_PXIe_self_test
 * @描述：		pxie板卡自检功能
 * @输入参数1：	vi			-	仪器句柄
 * @返回值：	函数执行正确，返回值大于等于0；执行时产生错误，返回值小于0
*/

ViStatus _VI_FUNC HITATCI_PXIe_self_test (ViSession vi)
{
    ViStatus errStatus = VI_SUCCESS;

    ViUInt32 rd_data[2], wr_data[2];

    // 读取0x0地址
    rd_data[0] = 0;
    errStatus = PXIe_viIn32 (vi, BAR0_SPACE, 0x0, &rd_data[0]);

    // 调整0x0地址数据
    wr_data[0] = rd_data[0] + 10;
    errStatus = PXIe_viOut32 (vi, BAR0_SPACE, 0x0, wr_data[0]);

    // 读取0x0地址
    rd_data[0] = 0;
    errStatus = PXIe_viIn32 (vi, BAR0_SPACE, 0x0, &rd_data[0]);

    // 读取0x0地址
    rd_data[0] = 0;
    errStatus = PXIe_viIn32 (vi, BAR0_SPACE, 0x0, &rd_data[0]);

    // 调整0x0地址数据
    wr_data[0] = rd_data[0] + 10;
    errStatus = PXIe_viOut32 (vi, BAR0_SPACE, 0x0, wr_data[0]);

    // 读取0x0地址
    rd_data[0] = 0;
    errStatus = PXIe_viIn32 (vi, BAR0_SPACE, 0x0, &rd_data[0]);

    // 测试失败
    if(rd_data[0] != wr_data[0]){
        return -1;
    }

	// 返回句柄
	return errStatus;
}

/****************************************************************
*HITATCI_PXIe_viIn32 32位读取寄存器
input:
vi：句柄
space：bar空间，0,1,2,3,4,5
offset：偏移量
val32：读取返回值
ViStatus:
函数操作结果
****************************************************************/
ViStatus _VI_FUNC  HITATCI_PXIe_viIn32(ViSession vi, ViUInt16 space, ViBusAddress offset, ViPUInt32 val32)
{
	ViStatus ret = VI_SUCCESS;

	ret = PXIe_viIn32(vi, space, offset, val32);

	return ret;
}

/****************************************************************
*HITATCI_PXIe_viOut32 32位写入寄存器
input:
vi：句柄
space：bar空间，0,1,2,3,4,5
offset：偏移量
val32：写入数据
ViStatus:
函数操作结果
****************************************************************/
ViStatus _VI_FUNC  HITATCI_PXIe_viOut32(ViSession vi, ViUInt16 space, ViBusAddress offset, ViUInt32  val32)
{
	ViStatus ret = VI_SUCCESS;

	ret = PXIe_viOut32(vi, space, offset, val32);

	return ret;
}

/****************************************************************
 * @函数名：	HITATCI_PXIe_viIn32_dma
 * @描述：		从FPGA读取数据
 * @输入参数1：     vi：句柄
 * @输入参数2：     space：bar空间，0,1,2,3,4,5
 * @输入参数3：     offset：偏移量
 * @输入参数4：     val32：存储读取序列的值
 * @输入参数5：     val32_len：读取的个数
 * @返回值：	函数执行正确，返回值大于等于0；执行时产生错误，返回值小于0
 ****************************************************************/
ViStatus _VI_FUNC  HITATCI_PXIe_viIn32_dma (ViSession vi, ViUInt16 space, ViBusAddress offset, ViPUInt32 val32, ViUInt32 val32_len)
{
    ViStatus ret = VI_SUCCESS;

    ret = PXIe_viIn32_dma (vi, space, offset, val32, val32_len);

    return ret;
}

/****************************************************************
 * @函数名：	HITATCI_PXIe_viOut32_dma
 * @描述：		向FPGA写入数据
 * @输入参数1：     vi：句柄
 * @输入参数2：     space：bar空间，0,1,2,3,4,5
 * @输入参数3：     offset：偏移量
 * @输入参数4：     val32：存储读取序列的值
 * @输入参数5：     val32_len：读取的个数
 * @返回值：	函数执行正确，返回值大于等于0；执行时产生错误，返回值小于0
 ****************************************************************/
ViStatus _VI_FUNC  HITATCI_PXIe_viOut32_dma (ViSession vi, ViUInt16 space, ViBusAddress offset, ViPUInt32  val32, ViUInt32 val32_len)
{
    ViStatus ret = VI_SUCCESS;

    ret = PXIe_viOut32_dma (vi, space, offset, val32, val32_len);

    return ret;
}

/****************************************************************
* @函数名：	HITMC_REG_LIST_OPT
* @描述：		向FPGA写入数据
* @输入参数1：     vi：句柄
* @输入参数2：     ListNum：操作序列的个数
* @输入参数3：     space：bar空间序列，0,1,2,3,4,5
* @输入参数4：     offset：偏移量序列
* @输入参数5：     val32：读取或者写入序列值
* @输入参数6：     OptMode：读取或者写入的序列值
* @输入参数7：     DelayTime：延时函数序列值
* @返回值：	函数执行正确，返回值大于等于0；执行时产生错误，返回值小于0
****************************************************************/
ViStatus _VI_FUNC HITMC_REG_LIST_OPT(ViSession vi, ViUInt32 ListNum, ViUInt16 *space, ViUInt32 *offset, ViUInt32 *val32, ViUInt32 * OptMode, ViUInt32 *DelayTime)
{
	ViStatus ret = VI_SUCCESS;
	ViUInt32 temp_i = 0;
	ViUInt32 milliseconds = 0;
	
	// 循环进行寄存器操作
	for (temp_i = 0; temp_i < ListNum; temp_i++) {
		// 从寄存器中读取数据
		if (OptMode[temp_i] == REG_READ_MODE) {
			ret = PXIe_viIn32(vi, space[temp_i], offset[temp_i], &val32[temp_i]);
		} 

		// 向寄存器中写入数据
		if (OptMode[temp_i] == REG_WRITE_MODE) {
			ret = PXIe_viOut32(vi, space[temp_i], offset[temp_i], val32[temp_i]);
		}

		// 延时，传递进来的时间是us，windows只能实现毫秒级延时，就做下处理
		milliseconds = 0;
		milliseconds = DelayTime[temp_i] / 1000;
		Sleep(milliseconds);
	}

	return ret;
}

